/**
 * 红外遥控简介: infrared remote control
 * 红外遥控是利用红外光进行通信的设备，由"红外LED"将调制后的信号发出，由专用的"红外接收头"进行解调输出
 * 通信方式：单工，异步 (没有时钟线, 需双方约定速率)
 * 红外LED波长：940nm (还有850nm的, 灯微亮, 用于红外不光[摄像头])
 * 通信协议标准：NEC标准
 * 
 * 红外接收头, 包含:
 *      1.红外接收管
 *      2.集成电路(滤波器,放大器, or其它)
 * 
 * 红外接收头需要接外部中断, (∵接收头没有缓存能力?), 如果循环判断, 可能信号都跑光了MCU才开始接受
 * 
 * 本发送与接收:
 *      空闲状态：红外LED不亮，接收头输出高电平
 *      发送低电平：红外LED以38KHz频率闪烁发光，接收头输出低电平
 *      发送高电平：红外LED不亮，接收头输出高电平
 * 
 * HS0038 使用的是 红外NEC协议编码
 * 
 * 由于要使用计数功能, TH, TL随时都可能清0, 所以另外使用1个定时器/计数器: Timer1
 */
#include "Timer1_Utils.h"
#include "Interrupt0_Utils.h"

static void Int0_onTick();

void IR_HS0038_Init() {
    //初始化定时器/计数器: 计数器模式
    Timer1_Init(0, 1);
    //初始化外部中断
    Int0_Init();
    //外部中断传入函数指针
    Int0_setOnTickListener(&Int0_onTick);
}

//                                        (bit isRepeat 会报错: indirect call: parameters do not fit within registers
static void (*IR_HS0038_onReceiveListener)(unsigned char isRepeat, unsigned char Address, unsigned char Command);
/**
 * 设置 IR_HS0038 红外收到数据的监听
 * TODO 写成 addListener 模式
 * @param IR_HS0038_onReceive 回调的函数指针, 示例: <br />
 *        //isRepeat: 是否是重复接收 (遥控器按住不放)
 *        //Address: 地址码 (遥控器的地址, 每种遥控器地址不一样?)
 *        //Command: 命令码 (遥控器按的按键的编号)
 *        static void IR_HS0038_onReceive(unsigned char isRepeat, unsigned char Address, unsigned char Command) {
 *            //do something...
 *        }
 *        //传入函数指针
 *        IR_HS0038_setOnTickListener(&IR_HS0038_onReceive);
 */
void IR_HS0038_setOnTickListener(void (*IR_HS0038_onReceive)(unsigned char isRepeat, unsigned char Address, unsigned char Command)) {
    IR_HS0038_onReceiveListener = IR_HS0038_onReceive;
}

//HS0038 使用的是 红外NEC协议编码
//TODO 红外NEC 是否应该抽取工具类?
static void Int0_onTick() {
    static float IR_HS0038_Time;                //获取2次下降沿间隔时间
    static unsigned char IR_HS0038_State = 0;   //记录状态
    //<< 最多16位, 再大会出错, 所以不用unsigned long (TODO 也许可以定义一个unsigned long xx = 1; ??)
    //static unsigned long IR_HS0038_Data;
    static unsigned char IR_HS0038_Data[4];     //接收4Byte数据
    static unsigned char IR_HS0038_pData = 0;       //控制写入数据位置
    // static unsigned char IR_HS0038_DataFlag = 0;
    // static unsigned char IR_HS0038_RepeatFlag = 0;//是否重复接收 (按住不放)
    static unsigned char IR_HS0038_Address;         //地址码
    static unsigned char IR_HS0038_Command;         //命令码

    //如果外部设置了接收数据的监听, HS0038 使用的是 红外NEC协议编码
    if (IR_HS0038_onReceiveListener) {
        if (IR_HS0038_State == 0) {     //Int0 第1个下降沿, 空闲状态
            Timer1_reset_TH_TL();
            Timer1_start();             //开始计数
            IR_HS0038_State = 1;
        } else if (IR_HS0038_State == 1) {
            IR_HS0038_Time = Timer1_getCounter_Time();          //Int0 第2个下降沿, 获取间隔时间
            Timer1_reset_TH_TL();                               //重新计数
            /**
             * Start: 启动信号, 9ms + 4.5ms = 13.5ms = 13500μs
             * 13000, 14000: ±500μs 误差
             */
            if (IR_HS0038_Time > 13000 && IR_HS0038_Time < 14000) {
                IR_HS0038_State = 2;
            } else if (IR_HS0038_Time > 10750 && IR_HS0038_Time < 11750) {
                //Repeat 重发信号: 9ms + 2.25ms = 11.25ms = 11250μs     11250-500=10750
                // IR_HS0038_RepeatFlag = 1;
                // IR_HS0038_onReceiveListener((bit)1, IR_HS0038_Address, IR_HS0038_Command);
                IR_HS0038_onReceiveListener(1, IR_HS0038_Address, IR_HS0038_Command);
                IR_HS0038_State = 0;            //状态
                Timer1_stop();                  //停止
            } else {
                IR_HS0038_State = 1;            //如果收到其它信号 (重复发送后 的数据信号)
            }
        } else if (IR_HS0038_State == 2) {      //解析数据
            IR_HS0038_Time = Timer1_getCounter_Time();
            Timer1_reset_TH_TL();
            //发送的0: 560μs + 560μs = 1120μs       1120-500=620
            if (IR_HS0038_Time > 620 && IR_HS0038_Time < 1620) {
                IR_HS0038_Data[IR_HS0038_pData / 8] &= ~(0x01 << (IR_HS0038_pData % 8));//数据对应位清0
                IR_HS0038_pData++;
            } else if (IR_HS0038_Time > 1750 && IR_HS0038_Time < 2750) {
                //发送的0: 560μs + 1690μs = 2250μs       1120-500=620
                IR_HS0038_Data[IR_HS0038_pData / 8] |= (0x01 << (IR_HS0038_pData % 8)); //数据对应位置1
                IR_HS0038_pData++;
            } else {
                //接收数据错误
                IR_HS0038_pData = 0;
                IR_HS0038_State = 1;
            }
            //如果4Byte数据 32位 接收完成
            if (IR_HS0038_pData >= 32) {
                IR_HS0038_pData = 0;
                IR_HS0038_State = 0;
                Timer1_stop();
                Timer1_reset_TH_TL();
                //验证数据
                if ((IR_HS0038_Data[0] == ~IR_HS0038_Data[1]) && (IR_HS0038_Data[2] == ~IR_HS0038_Data[3])) {
                    IR_HS0038_Address = IR_HS0038_Data[0];
                    IR_HS0038_Command = IR_HS0038_Data[2];
                    IR_HS0038_onReceiveListener(0, IR_HS0038_Address, IR_HS0038_Command);
                    // IR_HS0038_DataFlag = 1;
                }
            }
        }
    }
}
